package com.qf.chinatelcon.apigateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.qf.chinatelcon.apigateway.cache.ApiMappingLocalCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;

/**
 * 这个过滤器是网关将用户传递过来的服务给转发到真正的服务
 */
@Component
public class RouttingFilter extends ZuulFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(RouttingFilter.class);

    private ApiMappingLocalCache apiMappingLocalCache;

    @Autowired
    public void setApiMappingLocalCache(ApiMappingLocalCache apiMappingLocalCache) {
        this.apiMappingLocalCache = apiMappingLocalCache;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER+100;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();

        return context.sendZuulResponse();
    }

    @Override
    public Object run() throws ZuulException {
        //当前过滤器的作用是为了根据用户传递的某个数据的值抓发到相应的服务上，比如传递的是method我们就要根据method找到它的真实服务地址
        //我们要求传递一个method过来，就是根据这个值找到她的服务地址
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();//获取一个http请求
        String method = request.getParameter("method");//或去你的服务地址
        Map mapper = apiMappingLocalCache.getApiMapper(method);//获取当前用户传递的参数和地址
        if(mapper==null){
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseBody("没有找到该服务");//给用户反馈信息
            requestContext.addZuulResponseHeader("content-Type", "text/html;charset=utf-8");//设置传到网页的数据编码格式
            return null;
        }

        requestContext.set(FilterConstants.SERVICE_ID_KEY,mapper.get("serviceId"));
        String apiUrl = (String) mapper.get("insideApiUrl");//获取到转发的地址
        //我们发现了一个问题，就是我们的代码中充斥着大量的rest风格的编码格式，我们在讲地址发送过来的时候，我们无法根据他发送过来的地址
        //获取到我们最终像访问的地址，所以我们就需要进行改变替换，那麽如何进行替换，我们需要将{}中的key值换成我们需要的值，那麽我就需要用户
        //将想需要的地址传递过来，最终访问其相应的过程
        Enumeration<String> parameterNames = request.getParameterNames();//获取到所有的参数名称
        while (parameterNames.hasMoreElements()) {
            String element = parameterNames.nextElement();//获取到访问的地址名,这是获取到的key值名称
            String parameter = request.getParameter(element);//获取到这个名称对应的值,用户中与你在key名称后边跟着对应的名称值比如上边是key=name这个只相当于就是name
            LOGGER.error("参数名叫：{}，替换为{}替换前是{}", element, parameter,apiUrl);//将我们获取到的名字，替换成用户传递过来的名字
            apiUrl =  apiUrl.replace("{"+element+"}",parameter);//进行替换，将值进行替换
            LOGGER.error("替换Hou是{}",apiUrl);
        }
        requestContext.set(FilterConstants.REQUEST_URI_KEY,apiUrl);
        return null;
    }
}
